package main;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeMap;

import business.algorithm.decisionAlgorithm.MovingAverage;
import business.algorithm.decisionAlgorithm.Order;
import business.algorithm.decisionAlgorithm.OutputForDecisionAlgorithm;
import business.algorithm.predictAlgorithm.AutoRegressionFE;
import dataAccess.databaseManagement.entity.AssetEntity;
import dataAccess.databaseManagement.entity.ExchangeEntity;
import dataAccess.databaseManagement.entity.PriceEntity;
import dataAccess.databaseManagement.manager.AssetManager;
import dataAccess.databaseManagement.manager.ExchangeManager;
import dataAccess.databaseManagement.manager.PriceManager;

public class NewIndicator {
	public static HashMap<AssetEntity, ArrayList<PriceEntity>> references;
	public static ArrayList<PriceEntity> priceEntityList;

	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		BufferedWriter bufferedWriterResult = new BufferedWriter(
				new FileWriter(new File("predictResult.csv")));

		// choose testing asset and reference symbols
		ExchangeManager exchangeManager = new ExchangeManager();
		AssetManager assetManager = new AssetManager();
		PriceManager priceManager = new PriceManager();

		String[] referenceSymbols = {};
		references = new HashMap<AssetEntity, ArrayList<PriceEntity>>();

		for (int i = 0; i < referenceSymbols.length; ++i) {
			AssetEntity asset = assetManager.getAssetBySymbolAndExchange(
					referenceSymbols[i], "HOSE");
			ArrayList<PriceEntity> priceEntities = priceManager
					.getPriceByAssetID(asset.getAssetID());
			references.put(asset, priceEntities);
		}
		
		AssetEntity vnIndexAsset = assetManager.getAssetBySymbolAndExchange("^VNINDEX","INDEX");
		
		ArrayList<PriceEntity> vnIndex = priceManager.getPriceByAssetID(vnIndexAsset.getAssetID());
		//int vnIndexsize = vnIndex.size();

		ExchangeEntity exchangeEntity = exchangeManager
				.getExchangeByName("HOSE");
		ArrayList<AssetEntity> assetEntities = assetManager
				.getAssetsByExchange(exchangeEntity.getExchangeID());
		
		int maPeriod = 5;

		int noPredictedDates = 5;
		int noExpandedDates = 0;
		int noCrossValidation = 25;

		TreeMap<Double, ArrayList<String>> output = new TreeMap<Double, ArrayList<String>>(
				Collections.reverseOrder());

		// EMA
		ArrayList<PriceEntity> priceEntities = new ArrayList<PriceEntity>();
		for (int i = Math.max(
				vnIndex.size() - maPeriod*3, 0); i < vnIndex
				.size(); ++i) {
			priceEntities.add(vnIndex.get(i));
		}

		TreeMap<AssetEntity, ArrayList<PriceEntity>> map = new TreeMap<AssetEntity, ArrayList<PriceEntity>>();
		map.put(vnIndexAsset, priceEntities);

		MovingAverage movingAverage = new MovingAverage();
		movingAverage.setMA_period(maPeriod);
		movingAverage.setPriceList(map);

		OutputForDecisionAlgorithm outputDA = movingAverage
				.runAlgorithm();

		ArrayList<Order> orderList = outputDA.getOrderList();

		if (orderList.size() > 0
				&& orderList.get(orderList.size() - 1)
						.isOrderType() == Order.ORDER_BUY) {}{
			for (AssetEntity assetEntity : assetEntities) {		
				priceEntityList = priceManager.getPriceByAssetID(assetEntity.getAssetID());
				if (priceEntityList.size() < 100) {
					continue;
				}
	
	
	//			boolean flag = false;
	//			for (int n = 1; n < priceEntityList.size(); ++n) {
	//				double rate = priceEntityList.get(n).getClose()
	//						/ priceEntityList.get(n - 1).getClose() - 1;
	//				if ((rate < -0.06 || rate > 0.06)) {
	//					System.out.println(assetEntity.getSymbol() + ": "
	//							+ priceEntityList.get(n).getDate().toString());
	//					flag = true;
	//					break;
	//				}
	//			}
	//			if (flag) {
	//				continue;
	//			}
				
				System.out.println(assetEntity.getSymbol());
				
				String date = "Date";
				String real = "Real";
	
				for (int i = -10; i < 0; ++i) {
					date += ","
							+ priceEntityList.get(i + priceEntityList.size())
									.getDate();
					real += ","
							+ priceEntityList.get(i + priceEntityList.size())
									.getClose();
				}
	
				ArrayList<String> strOut = new ArrayList<String>();
				strOut.add(assetEntity.getSymbol());
				strOut.add(date);
				strOut.add(real);
	
	//			if (priceEntityList.get(priceEntityList.size() - 1).getLow() > priceEntityList.get(priceEntityList.size() - 2).getHigh()
	//					&& priceEntityList.get(priceEntityList.size() - 1).getVolume() > (vnIndex.get(vnIndexsize - 1).getVolume()/1000)
	//					&& priceEntityList.get(priceEntityList.size() - 1).getOpen() <= priceEntityList.get(priceEntityList.size() - 1).getClose()) {
				{
					// matching
	//				priceEntities = new ArrayList<PriceEntity>();
	//				for (int i = Math.max(priceEntityList.size() - 100,0); i < priceEntityList
	//						.size(); ++i) {
	//					priceEntities.add(priceEntityList.get(i));
	//				}
					
					double[][] result = predictUsingMatching(
							priceEntityList.size(), priceEntityList,
							noPredictedDates, noExpandedDates, noCrossValidation);
	
					double rate = new Double(result[0][result[0].length - 1]
							/ priceEntityList.get(priceEntityList.size() - 1)
									.getClose() - 1);
					
					String predict = "";
					for (int j = 0; j < result[0].length; ++j) {
						predict += "," + result[0][j];
					}
					strOut.add(predict);
	

					System.out.println(rate);

					output.put(rate, strOut);
	
				}
	
			}
		}

		for (Double roc : output.keySet()) {
			bufferedWriterResult.write(output.get(roc).get(0) + "," + roc);
			bufferedWriterResult.newLine();
			for (int i = 1; i < output.get(roc).size() - 2; ++i) {
				bufferedWriterResult.write(output.get(roc).get(i));
				bufferedWriterResult.newLine();
			}
			bufferedWriterResult.write(output.get(roc).get(
					output.get(roc).size() - 2));
			bufferedWriterResult.write(output.get(roc).get(
					output.get(roc).size() - 1));
			bufferedWriterResult.newLine();
		}

		bufferedWriterResult.close();
	}

	public static double[][] predictUsingMatching(int startDateIndex,
			ArrayList<PriceEntity> priceEntities, int noPredictedDates,
			int noExpandedDates, int crossValidationSize) throws IOException {

		MatchingAlgorithm matchingAlgorithm = new MatchingAlgorithm();
		matchingAlgorithm.setPriceEntities(priceEntities);
		matchingAlgorithm.setReferences(references);

		matchingAlgorithm.setInterval(25);
		matchingAlgorithm.setNoSample(3);
		return matchingAlgorithm.predict(startDateIndex, noPredictedDates, noExpandedDates);
	}

	public static double predictUsingARFE(int startDateIndex,
			ArrayList<PriceEntity> priceEntities, int noPredictedDates,
			int noExpandedDates, int crossValidationSize) {
		AssetManager assetManager = new AssetManager();
		ArrayList<PriceEntity> priceList = new ArrayList<PriceEntity>();

		for (int i = 0; i < startDateIndex; i++) {
			priceList.add(priceEntities.get(i));
		}

		AutoRegressionFE autoRegressionFE = new AutoRegressionFE();
		autoRegressionFE.setConfidenceLevel(0.9);
		autoRegressionFE.setFutureInterval(noPredictedDates);

		// Mean Square
		TreeMap<AssetEntity, ArrayList<PriceEntity>> map = new TreeMap<AssetEntity, ArrayList<PriceEntity>>();
		ArrayList<PriceEntity> training = new ArrayList<PriceEntity>();

		for (int k = priceList.size() - 100; k < priceList.size(); k++) {
			if (k < 0)
				continue;

			training.add(priceList.get(k));
		}

		map.put(assetManager.getAssetByID(priceList.get(0).getAssetID()),
				training);

		autoRegressionFE.setAR_period(5);
		autoRegressionFE.setPriceEntityList(map);

		double predict = 0;

		try {
			predict = autoRegressionFE.runAlgorithm().getPredictionPriceList()
					.firstEntry().getValue().get(noPredictedDates).getPrice();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return predict / priceEntities.get(startDateIndex - 1).getClose() - 1;
	}
}
